home *** CD-ROM | disk | FTP | other *** search
/ SPACE 2 / SPACE - Library 2 - Volume 1.iso / program / 615 / bez / bez.c next >
Encoding:
C/C++ Source or Header  |  1992-05-10  |  17.2 KB  |  974 lines

  1. /*
  2.  *    beztwist.c    17-Sep-88
  3.  *
  4.  *    Display some twisting cubic Bezier curves. Works with all 3
  5.  *    resolution modes of the Atari ST. Originally written for
  6.  *    Turbo C by (?).
  7.  *
  8.  *    note: this uses Bresenham's line drawing algorithm to write
  9.  *    directly to screen memory. it uses Physbase to find this. it
  10.  *    will work on all three "normal" screen resolutions (320x200x16 low,
  11.  *    640x200x4 med, and 640x400x2 high). it will probably not work with
  12.  *    other monitors.
  13.  *
  14.  *    compile:    gcc -mshort -O -o bez.ttp bez.c
  15.  */
  16.  
  17. #ifndef lint
  18. static char *rcsid = "$Id: bez.c,v 1.2 1992/05/09 19:05:46 rosenkra Exp $";
  19. #endif
  20.  
  21. /*
  22.  * $Log: bez.c,v $
  23.  * Revision 1.2  1992/05/09  19:05:46  rosenkra
  24.  * port to gnu C. nothing else done except reformatting source.
  25.  * major change was rand initialization. now uses time rather than
  26.  * 200 hz timer (which had bad code anyway). also changed INFO and
  27.  * BEZIER structs to typedefs.
  28.  *
  29.  */
  30.  
  31. #include <stdlib.h>            /* for rand,srand */
  32. #include <time.h>            /* for time */
  33. #include <osbind.h>            /* for Bios,Xbios,Gemdos calls */
  34.  
  35. #define WORD_BITS    16        /* screen "word" this size in bits */
  36.  
  37. #define low_res        0        /* screen resolution */
  38. #define med_res        1
  39. #define hi_res        2
  40.  
  41. #define    HI_PLANES    1        /* for hi rez */
  42. #define    HI_XMIN        0
  43. #define    HI_XMAX        639
  44. #define HI_YMIN        0
  45. #define    HI_YMAX        399
  46. #define HI_XWIDTH    640        /* (HI_XMAX - HI_XMIN + 1) */
  47. #define HI_YHEIGTH    400        /* (HI_YMAX - HI_YMIN + 1) */
  48. #define HI_WPLINE    40        /* (HI_PLANES * HI_XWIDTH / WORD_BITS)*/
  49. #define    HI_COLORS    2        /* (1 << HI_PLANES) */
  50.  
  51. #define    ME_PLANES    2        /* for med rez */
  52. #define    ME_XMIN        0
  53. #define    ME_XMAX        639
  54. #define    ME_YMIN        0
  55. #define    ME_YMAX        199
  56. #define ME_XWIDTH    640        /* (ME_XMAX - ME_XMIN + 1) */
  57. #define ME_YHEIGTH    200        /* (ME_YMAX - ME_YMIN + 1) */
  58. #define ME_WPLINE    80        /* (ME_PLANES * ME_XWIDTH / WORD_BITS)*/
  59. #define    ME_COLORS    4        /* (1 << ME_PLANES) */
  60.  
  61. #define LO_PLANES    4        /* for lo rez */
  62. #define    LO_XMIN        0
  63. #define    LO_XMAX        319
  64. #define    LO_YMIN        0
  65. #define    LO_YMAX        199
  66. #define    LO_XWIDTH    (LO_XMAX - LO_XMIN + 1)
  67. #define LO_YHEIGTH    (LO_YMAX - LO_YMIN + 1)
  68. #define LO_WPLINE    (LO_PLANES * LO_XWIDTH / WORD_BITS)
  69. #define LO_COLORS    (1 << LO_PLANES)
  70.  
  71. #define CHANGE        0x0f        /* how often to change colors */
  72. #define    NQ        10        /* length of FIFO queue */
  73. #define MAXNQ        50        /* max number of lines (-l) */
  74. #define    FLAT        32L        /* for area convergence */
  75. #define CONSOLE        2        /* BIOS console */
  76.  
  77. #define    BITS        5
  78. #define SCALE        (1 << BITS)
  79. #define SCALE2        (1 << (BITS-1))
  80.  
  81.  
  82. /*
  83.  *    screen info
  84.  */
  85. typedef struct
  86. {
  87.     unsigned int   *i_screen;
  88.     int        i_res;
  89.     long        i_planes,
  90.             i_wpline;
  91.     unsigned int    i_color,
  92.             i_colmask;
  93.     long        i_xmax,
  94.             i_ymax;
  95.     long        i_maxarea;
  96. } info_t;
  97.  
  98.  
  99. /*
  100.  *    curve info
  101.  */
  102. typedef struct
  103. {
  104.     long        b_x[4];
  105.     long        b_y[4];
  106.     int        b_active;
  107.  
  108. } bez_t;
  109.  
  110.  
  111.  
  112. int    grayscale = 0;                /* for color gray palette */
  113.  
  114.  
  115. /*
  116.  *    local functions
  117.  */
  118. void    bezier ();
  119. void    draw_line ();
  120. void    rand_init ();
  121. void    set_color ();
  122. void    usage ();
  123.  
  124.  
  125.  
  126.  
  127. /*------------------------------*/
  128. /*    main            */
  129. /*------------------------------*/
  130. void main (argc, argv)
  131. int     argc;
  132. char   *argv[];
  133. {
  134.  
  135. /*
  136.  *    Show some randomly twisting bezier curves.
  137.  */
  138.  
  139.     info_t        info;        /* screen info */
  140.     bez_t        list[MAXNQ];    /* list of curves */
  141.     bez_t           *q;        /* current one */
  142.     long        dx[4],
  143.             dy[4];
  144.     long           *p;
  145.     unsigned int    colr;
  146.     int        i,
  147.                 j,
  148.                 k,
  149.                 n;
  150.     long        loop,
  151.                 flat;
  152.     int        lines,
  153.             change;
  154.     int        tmp1, tmp2;
  155.  
  156.  
  157.  
  158.  
  159.     /*
  160.      *   initialize rand ()
  161.      */
  162.     rand_init ();
  163.  
  164.  
  165.  
  166.     /*
  167.      *   where HARDWARE screen is. we write there directly for speed
  168.      */
  169.     info.i_screen = Physbase ();
  170.  
  171.  
  172.  
  173.     /*
  174.      *   get resolution
  175.      */
  176.     info.i_res = Getrez ();
  177.  
  178.  
  179.  
  180.     /*
  181.      *   all this does is clear the screen...
  182.      */
  183.     Setscreen (-1L, -1L, (int) info.i_res);
  184.  
  185.  
  186.  
  187.     /*
  188.      *   cmdline args.
  189.       *   first is number of curves (def = NQ)
  190.      *   second is loop counter. if +ve, only draw loop times. if -ve,
  191.      *   loop infinite.
  192.      *   third is convergence factor. the larger it is, the faster it
  193.      *   converges. try 50-1000.
  194.      */
  195.     lines  = NQ;
  196.     loop   = -1,
  197.     flat   = 0;
  198.     change = CHANGE;
  199.  
  200.     argc--, argv++;
  201.     while (argc)
  202.     {
  203.         if (**argv != '-')
  204.         {
  205.             usage ();
  206.  
  207.             exit (0);
  208.         }
  209.         switch (*(*argv+1))
  210.         {
  211.         case 'h':
  212.         case 'H':
  213.             usage ();
  214.             exit (0);
  215.         case 'l':
  216.         case 'L':
  217.             argc--, argv++;
  218.             lines = atoi (*argv);
  219.             if (lines > MAXNQ)
  220.                 lines = MAXNQ;
  221.             break;
  222.         case 'n':
  223.         case 'N':
  224.             argc--, argv++;
  225.             loop = atoi (*argv);
  226.             break;
  227.         case 'f':
  228.         case 'F':
  229.             argc--, argv++;
  230.             flat = atoi (*argv);
  231.             break;
  232.         case 'c':
  233.         case 'C':
  234.             argc--, argv++;
  235.             change = atoi (*argv);
  236.             break;
  237.         case 'g':
  238.         case 'G':
  239.             grayscale = 1;
  240.             break;
  241.         }
  242.         argc--, argv++;
  243.     }
  244.     if (loop < 1)
  245.         loop = -1;
  246.     if (change < 1)
  247.         change = CHANGE;
  248.  
  249.  
  250.  
  251.     /*
  252.      *   save color pal and reset to new one
  253.      */
  254.     set_color ((int) info.i_res, 1);
  255.  
  256.  
  257.  
  258.     /*
  259.      *   fill in info struct based on resolution
  260.      */
  261.     switch (info.i_res)
  262.     {
  263.     case hi_res: 
  264.         info.i_xmax    = HI_XMAX;
  265.         info.i_ymax    = HI_YMAX;
  266.         info.i_planes  = HI_PLANES;
  267.         info.i_wpline  = HI_WPLINE;
  268.         info.i_maxarea = (flat >= 1 ? flat : FLAT) * SCALE * SCALE;
  269.         info.i_colmask = HI_COLORS - 1;
  270.         colr = HI_COLORS - 1;
  271.         break;
  272.  
  273.     case med_res: 
  274.         info.i_xmax    = ME_XMAX;
  275.         info.i_ymax    = ME_YMAX;
  276.         info.i_planes  = ME_PLANES;
  277.         info.i_wpline  = ME_WPLINE;
  278.         info.i_maxarea = (flat >= 1 ? flat : (3 * FLAT) / 4) * SCALE * SCALE;
  279.         info.i_colmask = ME_COLORS - 1;
  280.         colr = ME_COLORS - 1;
  281.         break;
  282.  
  283.     case low_res: 
  284.         info.i_xmax    = LO_XMAX;
  285.         info.i_ymax    = LO_YMAX;
  286.         info.i_planes  = LO_PLANES;
  287.         info.i_wpline  = LO_WPLINE;
  288.         info.i_maxarea = (flat >= 1 ? flat : FLAT / 2) * SCALE * SCALE;
  289.         info.i_colmask = LO_COLORS - 1;
  290.         colr = LO_COLORS - 1;
  291.         break;
  292.  
  293.     default: 
  294.         exit (-1);
  295.     }
  296.  
  297.  
  298.  
  299.     /*
  300.      *   initialize
  301.      */
  302.     for (i = 1; i < lines; i++)
  303.         list[i].b_active = 0;
  304.  
  305.  
  306.  
  307.     /*
  308.      *   init things...loop is to make an initial surface (4 pts)
  309.      */
  310.     i           = 0;
  311.     q           = &(list[0]);
  312.     q->b_active = 1;
  313.  
  314.     for (k = 0; k < 4; k++)
  315.     {
  316.         tmp1      = rand ();
  317.         tmp2      = (int) info.i_xmax;
  318.         q->b_x[k] = (long) (tmp1 % tmp2);
  319.         tmp1      = rand ();
  320.         tmp2      = (int) info.i_ymax;
  321.         q->b_y[k] = (long) (tmp1 % tmp2);
  322.  
  323.         n = (rand () & 15) - 7;
  324.         if (n == 0)
  325.             n = 1;
  326.         else if (n == 8)
  327.             n = -1;
  328.         dx[k] = n;
  329.  
  330.         n = (rand () & 15) - 7;
  331.         if (n == 0)
  332.             n = 1;
  333.         else if (n == 8)
  334.             n = -1;
  335.         dy[k] = n;
  336.     }
  337.  
  338.  
  339.  
  340.     /*
  341.      *   do it. loop starts out -1 unless there is a cmdline arg so it
  342.      *   does this until a key is pressed
  343.      */
  344.     while (loop--)
  345.     {
  346.         /*
  347.          *   draw the current line...
  348.          */
  349.         info.i_color = colr;
  350.         bezier (&info,
  351.             (long)(q->b_x[0] * SCALE + SCALE2),
  352.             (long)(q->b_y[0] * SCALE + SCALE2),
  353.             (long)(q->b_x[1] * SCALE + SCALE2),
  354.             (long)(q->b_y[1] * SCALE + SCALE2),
  355.             (long)(q->b_x[2] * SCALE + SCALE2),
  356.             (long)(q->b_y[2] * SCALE + SCALE2),
  357.             (long)(q->b_x[3] * SCALE + SCALE2),
  358.             (long)(q->b_y[3] * SCALE + SCALE2));
  359.  
  360.  
  361.         /*
  362.          *   j is last one, i is next one (q -> next)
  363.          */
  364.         j = i;
  365.         i = (i + 1) % lines;
  366.         q = &(list[i]);
  367.  
  368.  
  369.         /*
  370.          *   if next one is active, it was drawn already so undraw it
  371.          */
  372.         if (q->b_active)
  373.         {
  374.             info.i_color = 0;
  375.             bezier (&info,
  376.                 (long)(q->b_x[0] * SCALE + SCALE2),
  377.                 (long)(q->b_y[0] * SCALE + SCALE2),
  378.                 (long)(q->b_x[1] * SCALE + SCALE2),
  379.                 (long)(q->b_y[1] * SCALE + SCALE2),
  380.                 (long)(q->b_x[2] * SCALE + SCALE2),
  381.                 (long)(q->b_y[2] * SCALE + SCALE2),
  382.                 (long)(q->b_x[3] * SCALE + SCALE2),
  383.                 (long)(q->b_y[3] * SCALE + SCALE2));
  384.         }
  385.  
  386.  
  387.         /*
  388.          *   is this needed???
  389.          */
  390.         q->b_active = 1;
  391.  
  392.  
  393.         /*
  394.          *   set up points for next one...
  395.          */
  396.         for (k = 0; k < 4; k++)
  397.         {
  398.             p  = &(q->b_x[k]);
  399.             *p = list[j].b_x[k] + dx[k];
  400.             if (*p < 0)
  401.             {
  402.                 *p   += 8;
  403.                 dx[k] = -dx[k];
  404.             }
  405.             else if (*p > info.i_xmax)
  406.             {
  407.                 *p   -= 8;
  408.                 dx[k] = -dx[k];
  409.             }
  410.  
  411.             p  = &(q->b_y[k]);
  412.             *p = list[j].b_y[k] + dy[k];
  413.             if (*p < 0)
  414.             {
  415.                 *p   += 8;
  416.                 dy[k] = -dy[k];
  417.             }
  418.             else if (*p > info.i_ymax)
  419.             {
  420.                 *p   -= 8;
  421.                 dy[k] = -dy[k];
  422.             }
  423.         }
  424.  
  425.  
  426.         /*
  427.          *   every change times thru change color and direction...
  428.          */
  429.         if ((loop & change) == 0)
  430.         {
  431.             /*
  432.              *   change direction
  433.              */
  434.             k = rand () & 3;
  435.             n = (rand () & 15) - 7;
  436.             if (n == 0)
  437.                 n = 1;
  438.             else if (n == 8)
  439.                 n = -1;
  440.             if (rand () & 1)
  441.                 dx[k] = n;
  442.             else
  443.                 dy[k] = n;
  444.  
  445.             /*
  446.              *   change color
  447.              */
  448.             colr = (rand () % info.i_colmask) + 1;
  449.  
  450.             loop = -1;
  451.         }
  452.  
  453.         /*
  454.          *   exit if any key pressed, set to finish
  455.          */
  456.         if (Bconstat (CONSOLE))
  457.             loop = 0;
  458.     }
  459.  
  460.  
  461.  
  462.     /*
  463.      *   clear key press
  464.      */
  465.     while (Bconstat (CONSOLE))
  466.         (void) Bconin (CONSOLE);
  467.  
  468.  
  469.  
  470.     /*
  471.      *   set screen colors back...
  472.      */
  473.     set_color ((int) info.i_res, 0);
  474.  
  475.  
  476.     exit (0);
  477. }
  478.  
  479.  
  480.  
  481.  
  482. /*------------------------------*/
  483. /*    bezier            */
  484. /*------------------------------*/
  485. void bezier (pinfo, x0, y0, x1, y1, x2, y2, x3, y3)
  486. info_t *pinfo;
  487. long    x0;
  488. long    y0;
  489. long    x1;
  490. long    y1;
  491. long    x2;
  492. long    y2;
  493. long    x3;
  494. long    y3;
  495. {
  496.  
  497. /*    bezier()
  498.  *
  499.  *    Draw the cubic (2d) Bezier curve specified by P0, P1, P2 and P3
  500.  *    by subdividing it recursively into sub-curves until it
  501.  *    can be approximated smoothly by straight line segments.
  502.  *    We use fixed point arithmetic to achieve increased precision
  503.  *    in coordinate computations. The control points have been
  504.  *    scaled with SCALE and 0.5 has been added to the coordinates
  505.  *    so that we can feed rounded coordinate values to draw_line().
  506.  */
  507.  
  508.     long    v1x,
  509.             v1y,
  510.             v2x,
  511.             v2y,
  512.             v3x,
  513.             v3y;
  514.     long    vcp1,
  515.             vcp2,
  516.             vcp3,
  517.             area;
  518.     long    mid_x,
  519.             mid_y;
  520.     int     code;
  521.  
  522.  
  523.  
  524.     /* 
  525.      *   Stop the recursion when the size of the area covered
  526.      *   by the convex hull of the Bezier curve is less than or
  527.      *   equal to pinfo->i_maxarea.
  528.      */
  529.  
  530.  
  531.  
  532.     /*
  533.      *   First, compute direction vectors
  534.      */
  535.     v3x = x3 - x0;
  536.     v3y = y3 - y0;
  537.     v2x = x2 - x0;
  538.     v2y = y2 - y0;
  539.     v1x = x1 - x0;
  540.     v1y = y1 - y0;
  541.  
  542.  
  543.  
  544.     /*
  545.      *   Then, compute vector cross products.
  546.      */
  547.     code = 0;
  548.     if ((vcp1 = v3x * v2y - v2x * v3y) < 0)
  549.         code += 4;
  550.     if ((vcp2 = v3x * v1y - v1x * v3y) < 0)
  551.         code += 2;
  552.     if ((vcp3 = v2x * v1y - v1x * v2y) < 0)
  553.         code += 1;
  554.  
  555.  
  556.  
  557.     /*
  558.      *   Finally, compute size of area covered by convex hull
  559.      *
  560.      *   We actually compute 2*area, but that doesn't matter much.
  561.      */
  562.     switch (code)
  563.     {
  564.     case 0: 
  565.     case 2: 
  566.     case 5: 
  567.     case 7: 
  568.         area = vcp1 + vcp3;
  569.         break;
  570.     case 1: 
  571.     case 6: 
  572.         area = vcp2 - vcp3;
  573.         break;
  574.     case 3: 
  575.     case 4: 
  576.         area = vcp1 - vcp2;
  577.         break;
  578.     default: 
  579.         return;
  580.     }
  581.  
  582.     if (code & 4)
  583.         area = -1 * area;
  584.  
  585.  
  586.  
  587.     /*
  588.      *   converged?
  589.      */
  590.     if (area <= pinfo->i_maxarea)
  591.     {
  592.         /*
  593.          *   Yes. Stop recursion and draw a line from P0 to P3.
  594.          *
  595.          *   Rescale and round coordinates before
  596.          *   feeding them to draw_line()
  597.          */
  598.         draw_line (pinfo,
  599.             ((long) x0) >> BITS,
  600.             ((long) y0) >> BITS,
  601.             ((long) x3) >> BITS,
  602.             ((long) y3) >> BITS);
  603.  
  604.         return;
  605.     }
  606.     else
  607.     {
  608.         /*
  609.          *   No. Area is still too big, so subdivide the curve into
  610.          *   two sub-curves and draw these recursively.
  611.          */
  612.         mid_x = (long) (x0 + (3 * x1) + (3 * x2) + x3) >> 3;
  613.         mid_y = (long) (y0 + (3 * y1) + (3 * y2) + y3) >> 3;
  614.  
  615.         bezier (pinfo,
  616.             (long) x0,
  617.             (long) y0,
  618.             (long) (x0 + x1) >> 1,
  619.             (long) (y0 + y1) >> 1,
  620.             (long) (x0 + (2 * x1) + x2) >> 2,
  621.             (long) (y0 + (2 * y1) + y2) >> 2,
  622.             (long) mid_x,
  623.             (long) mid_y);
  624.  
  625.         bezier (pinfo,
  626.             (long) mid_x,
  627.             (long) mid_y,
  628.             (long) (x1 + (2 * x2) + x3) >> 2,
  629.             (long) (y1 + (2 * y2) + y3) >> 2,
  630.             (long) (x2 + x3) >> 1,
  631.             (long) (y2 + y3) >> 1,
  632.             (long) x3,
  633.             (long) y3);
  634.  
  635.         return;
  636.     }
  637. }
  638.  
  639.  
  640.  
  641.  
  642. /*------------------------------*/
  643. /*    draw_line        */
  644. /*------------------------------*/
  645. void draw_line (pinfo, x_from, y_from, x_to, y_to)
  646. register info_t *pinfo;
  647. register long    x_from;
  648. long        y_from;
  649. long        x_to;
  650. long        y_to;
  651. {
  652.  
  653. /*
  654.  *    Draw a line from point (x_from, y_from) to point (x_to, y_to).
  655.  *    Use Bresenham's line drawing algorithm with incremental
  656.  *    screen address computation and inline plotting. (Fast!)
  657.  */
  658.  
  659.     register unsigned int  *scrn;
  660.     register unsigned int    or_mask;
  661.     register unsigned int    and_mask;
  662.     register unsigned int    colr;
  663.     long            del_x,
  664.                 del_y,
  665.                 inc_left,
  666.                 inc_lup;
  667.     long            count,
  668.                 dist,
  669.                 offset;
  670.     int            flag;
  671.  
  672.  
  673.  
  674.  
  675.     /*
  676.      *   find motion
  677.      */
  678.     del_y = y_to - y_from;
  679.  
  680.     if ((del_x = x_to - x_from) < 0)
  681.     {
  682.         del_x = -del_x;
  683.         del_y = -del_y;
  684.         x_from = x_to;
  685.         y_from = y_to;
  686.     }
  687.  
  688.     if (del_y < 0)
  689.     {
  690.         offset = -(pinfo->i_wpline);
  691.         del_y = -del_y;
  692.     }
  693.     else
  694.     {
  695.         offset = pinfo->i_wpline;
  696.     }
  697.  
  698.     if (del_x < del_y)
  699.     {
  700.         flag = 1;
  701.         count = del_y;
  702.         del_y = del_x;
  703.         del_x = count;
  704.     }
  705.     else
  706.     {
  707.         flag = 0;
  708.         count = del_x;
  709.     }
  710.  
  711.  
  712.  
  713.     /*
  714.      *   this calculates the word in screen memory where we wish to plot
  715.      */
  716.     scrn = (unsigned int *) (pinfo->i_screen +
  717.            (y_from * pinfo->i_wpline) + ((x_from >> 4) * pinfo->i_planes));
  718.  
  719.  
  720.  
  721.     /*
  722.      *   now set the mask for the actual pixel in the word...
  723.      */
  724.     or_mask  = 0x8000 >> (int) (x_from & 0x0000000FL);
  725.     inc_left = 2 * del_y;
  726.     dist     = inc_left - del_x;
  727.     inc_lup  = dist - del_x;
  728.     colr     = pinfo->i_color;
  729.  
  730.  
  731.  
  732.     /*
  733.      *   loop until all points in the segment are "drawn"
  734.      */
  735.     for (;;)
  736.     {
  737.         and_mask = ~or_mask;
  738.  
  739.         switch (pinfo->i_res)
  740.         {
  741.         case low_res: 
  742.             if (colr & 8)
  743.                 scrn[3] |= or_mask;
  744.             else
  745.                 scrn[3] &= and_mask;
  746.             if (colr & 4)
  747.                 scrn[2] |= or_mask;
  748.             else
  749.                 scrn[2] &= and_mask;
  750.             /*FALL THRU...*/
  751.         case med_res: 
  752.             if (colr & 2)
  753.                 scrn[1] |= or_mask;
  754.             else
  755.                 scrn[1] &= and_mask;
  756.             /*FALL THRU...*/
  757.         case hi_res: 
  758.             if (colr & 1)
  759.                 scrn[0] |= or_mask;
  760.             else
  761.                 scrn[0] &= and_mask;
  762.             /*FALL THRU...*/
  763.         default: 
  764.             break;
  765.         }
  766.  
  767.  
  768.  
  769.         /*
  770.          *   we done?
  771.          */
  772.         if (count <= 0)
  773.             break;
  774.         count--;
  775.  
  776.  
  777.         if (dist >= 0)
  778.         {
  779.             /*
  780.              *   Move 1 pixel 'left' and 'up'.
  781.              */
  782.             dist     += inc_lup;
  783.             or_mask >>= 1;
  784.             scrn     += offset;
  785.         }
  786.         else
  787.         {
  788.             /*
  789.              *   Move 1 pixel 'left'.
  790.              */
  791.             dist += inc_left;
  792.             if (flag)
  793.                 scrn += offset;
  794.             else
  795.                 or_mask >>= 1;
  796.         }
  797.  
  798.  
  799.  
  800.         /*
  801.          *   wraparound
  802.          */
  803.         if (or_mask == 0x0000)
  804.         {
  805.             scrn += pinfo->i_planes;
  806.             or_mask = 0x8000;
  807.         }
  808.     }
  809.  
  810.     return;
  811. }
  812.  
  813.  
  814.  
  815.  
  816. /*------------------------------*/
  817. /*    rand_init        */
  818. /*------------------------------*/
  819. void rand_init ()
  820. {
  821.  
  822. /*
  823.  *   set rand by getting current time via time
  824.  */
  825.     long    seed;
  826.  
  827.     seed = (long) time ((time_t *) 0);
  828.     srand ((int) seed);
  829. }
  830.  
  831.  
  832.  
  833.  
  834. /*-----------------------------*/
  835. /*    set_color           */
  836. /*-----------------------------*/
  837.  
  838. int    old_palette[16];
  839.  
  840. int    hi_palette[16] = 
  841.     {    /*RGB*/
  842.         0x000,            /* black (gackground) */
  843.         0x777,            /* white */
  844.  
  845.         0x444,    0x444,    0x444,    0x444,    0x444,    0x444,    0x444,
  846.         0x444,    0x444,    0x444,    0x444,    0x444,    0x444,    0x444
  847.     };
  848.  
  849. int    med_palette[16] = 
  850.     {    /*RGB*/
  851.         0x000,            /* black (gackground) */
  852.         0x700,            /* red */
  853.         0x070,            /* green */
  854.         0x007,            /* blue */
  855.  
  856.         0x444,    0x444,    0x444,    0x444,    0x444,    0x444,
  857.         0x444,    0x444,    0x444,    0x444,    0x444,    0x444
  858.     };
  859.  
  860. int    med_gray_palette[16] =         /* alternate for gray-scale... */
  861.     {    /*RGB*/
  862.         0x000,            /* black (gackground) */
  863.         0x777,
  864.         0x444,
  865.         0x222,
  866.  
  867.         0x444,    0x444,    0x444,    0x444,    0x444,    0x444,
  868.         0x444,    0x444,    0x444,    0x444,    0x444,    0x444
  869.     };
  870.  
  871. int    lo_palette[16] = 
  872.     {    /*RGB*/
  873.         0x000,            /* black (gackground) */
  874.         0x700,            /* red */
  875.         0x070,            /* green */
  876.         0x007,            /* blue */
  877.         0x077,            /* cyan */
  878.         0x770,            /* yellow */
  879.         0x707,            /* magenta */
  880.         0x777,            /* white */
  881.         0x742,            /* orange */
  882.         0x517,            /* purple */
  883.         0x520,            /* brown */
  884.         0x444,            /* gray */
  885.         0x744,            /* lt red */
  886.         0x574,            /* lt green */
  887.         0x467,            /* lt blue */
  888.         0x666            /* lt gray */
  889.     };
  890.  
  891. int    lo_gray_palette[16] =          /* alternate for gray-scale... */
  892.     {    /*RGB*/
  893.         0x000,            /* black (gackground) */
  894.         0x777,            /* white */
  895.         0x666,
  896.         0x555,
  897.         0x444,
  898.         0x333,
  899.         0x222,
  900.         0x111,
  901.         0x777,
  902.         0x666,
  903.         0x555,
  904.         0x444,
  905.         0x333,
  906.         0x222,
  907.         0x111,
  908.         0x777
  909.     };
  910.  
  911. void set_color (res, opt)
  912. int    res;
  913. int    opt;                /* 1=set, 0=reset to orig */
  914. {
  915.     int    i;
  916.  
  917.     if (opt)
  918.     {
  919.         /*
  920.          *   save user's palette and load our own
  921.          */
  922.         for (i = 0; i < 16; i++)
  923.             old_palette[i] = Setcolor (i, -1);
  924.  
  925.         switch (res)
  926.         {
  927.         case 0:                /* low */
  928.             if (grayscale)
  929.                 Setpalette (lo_gray_palette);
  930.             else
  931.                 Setpalette (lo_palette);
  932.             break;
  933.  
  934.         case 1:                /* med */
  935.             if (grayscale)
  936.                 Setpalette (med_gray_palette);
  937.             else
  938.                 Setpalette (med_palette);
  939.             break;
  940.  
  941.         case 2:                /* hi */
  942.             Setpalette (hi_palette);
  943.             break;
  944.         }
  945.     }
  946.     else
  947.     {
  948.         /*
  949.          * reset to user's palette before exit
  950.          */
  951.         Setpalette (old_palette);
  952.     }
  953.  
  954.     return;
  955.  
  956. }
  957.  
  958.  
  959.  
  960.  
  961. /*-----------------------------*/
  962. /*    usage               */
  963. /*-----------------------------*/
  964. void usage ()
  965. {
  966.     Cconws ("\r\nUsage:  bez [-l lines] [-n times] [-f converge] [-c changefreq] [-gray]\n\r");
  967.     Cconws ("\r\n\n\nAny key...");
  968.     while (!(Bconstat (CONSOLE)))
  969.         ;
  970.     (void) Bconin (CONSOLE);
  971.     Cconws ("\r\n");
  972. }
  973.  
  974.